/*
 * Copyright (C) 2020 The LINN Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.juqimiao.linn.event;

import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.juqimiao.linn.event.AsyncEventBus;
import com.juqimiao.linn.event.Dispatcher;
import com.juqimiao.linn.event.EventBus;
import com.juqimiao.linn.exception.BasicError;
import com.juqimiao.linn.exception.FrameworkException;
import com.juqimiao.linn.exception.SystemException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.*;

/**
 * 配置应程序范围内的EventBus实例。其名称为"mainline_asyn_event_bus"。
 *
 * @author Collin Cai
 */
@Configuration
public class EventConfig {

   // private AsyncEventBus asyncEventBus = new AsyncEventBus("mainline_asyn_event_bus", buildExecutor());

    /**
     * 获取主EventBus的bean, busid: mainline_event_bus.
     *
     * @return 一个 {@link EventBus} 对象。
     */
    @Bean
    public EventBus getEventBus() {
        return new EventBus("mainline_event_bus",
                MoreExecutors.directExecutor(),
                Dispatcher.perThreadDispatchQueue(),
                EventBus.CommonHandler.INSTANCE,
                true);
    }

    private ThreadPoolExecutor buildExecutor() {
        int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
        int maximumPoolSize = Runtime.getRuntime().availableProcessors() + 1;
        long keepAliveTime = 0L;
        TimeUnit unit = TimeUnit.MILLISECONDS;
        BlockingQueue<Runnable> blockingQueue = new LinkedBlockingDeque<Runnable>(1000);
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("event-pool-%d").build();
        return new ThreadPoolExecutor(corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                blockingQueue,
                threadFactory);
    }
}
